home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.orig.lzh / input / newsspool.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  6KB  |  291 lines

  1. /*
  2.  * newsspool - copy incoming news into incoming directory
  3.  *
  4.  * The -i option relies on the parent setting (and exporting) $PATH.
  5.  *
  6.  * $Log$
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <string.h>
  13. #include <errno.h>
  14. #include "libc.h"
  15. #include "news.h"
  16. #include "config.h"
  17.  
  18. #ifndef lint
  19. static char RCSid[] = "$Header$";
  20. #endif
  21.  
  22. #ifndef MAXTRIES
  23. #define    MAXTRIES    100    /* limit on attempts to make links */
  24. #endif
  25.  
  26. int debug = 0;
  27. char *progname;
  28.  
  29. extern void error(), exit();
  30. #ifdef UTZOOERR
  31. extern char *mkprogname();
  32. #else
  33. #define    mkprogname(a)    (a)
  34. #endif
  35.  
  36. char buf[BUFSIZ*16];    /* try to get a batch in a few gulps */
  37. int immed = 0;        /* try an immediate newsrun? */
  38.  
  39. void process();
  40. FILE *outopen();
  41. void outclose();
  42. extern time_t time();
  43. char *outname();
  44.  
  45. /*
  46.  - main - parse arguments and handle options
  47.  */
  48. main(argc, argv)
  49. int argc;
  50. char *argv[];
  51. {
  52.     int c;
  53.     int errflg = 0;
  54.     FILE *in;
  55.     struct stat statbuf;
  56.     extern int optind;
  57.     extern char *optarg;
  58.     extern FILE *efopen();
  59.     void process();
  60.  
  61.     progname = mkprogname(argv[0]);
  62.  
  63.     while ((c = getopt(argc, argv, "id")) != EOF)
  64.         switch (c) {
  65.         case 'i':    /* try immediate newsrun */
  66.             immed++;
  67.             break;
  68.         case 'd':    /* Debugging. */
  69.             debug++;
  70.             setbuf(stderr, (char *)NULL);
  71.             break;
  72.         case '?':
  73.         default:
  74.             errflg++;
  75.             break;
  76.         }
  77.     if (errflg) {
  78.         fprintf(stderr, "usage: %s [file] ...\n", progname);
  79.         exit(2);
  80.     }
  81.  
  82.     /* probe to get unprivileged() called if necessary */
  83.     (void) ctlfile((char *)NULL);
  84.  
  85.     /* mktemp() uses access(2) [ARGH!] so minimize chances of trouble */
  86.     (void) setgid(getegid());
  87.     (void) setuid(geteuid());
  88.  
  89.     (void) umask(newsumask());
  90.  
  91.     if (optind >= argc)
  92.         process(stdin, "stdin");
  93.     else
  94.         for (; optind < argc; optind++)
  95.             if (STREQ(argv[optind], "-"))
  96.                 process(stdin, "-");
  97.             else {
  98.                 in = efopen(argv[optind], "r");
  99.                 if (fstat(fileno(in), &statbuf) < 0)
  100.                     error("can't fstat `%s'", argv[optind]);
  101.                 if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
  102.                     error("`%s' is directory!", argv[optind]);
  103.                 process(in, argv[optind]);
  104.                 (void) fclose(in);
  105.             }
  106.  
  107.     if (immed) {
  108.         execlp("newsrun", "newsrun", (char *)NULL);
  109.         error("attempt to run newsrun failed!", "");
  110.     }
  111.     exit(0);
  112. }
  113.  
  114. /*
  115.  * process - process input file
  116.  */
  117. /* ARGSUSED */
  118. void
  119. process(in, inname)
  120. FILE *in;
  121. char *inname;
  122. {
  123.     register int count;
  124.     register int firstblock;
  125.     FILE *out;
  126.     register char *p;
  127.     register int n;
  128.     char *name;
  129.  
  130.     name = outname();
  131.     out = outopen(name);
  132.  
  133.     /* do the copying */
  134.     firstblock = 1;
  135.     while ((count = fread(buf, sizeof(char), sizeof(buf), in)) > 0) {
  136.         if (firstblock) {
  137.             n = cunskip(buf, count);
  138.             p = buf + n;
  139.             count -= n;
  140.             firstblock = 0;
  141.         } else
  142.             p = buf;
  143.         n = fwrite(p, sizeof(char), count, out);
  144.         if (n != count)
  145.             error("write error in output to `%s'", name);
  146.     }
  147.  
  148.     outclose(out, name);
  149. }
  150.  
  151. /*
  152.  - outname - construct name for the temporary output file
  153.  */
  154. char *
  155. outname()
  156. {
  157.     register char *p;
  158.  
  159.     p = strsave(fullartfile("in.coming/nspool.XXXXXX"));
  160.     mktemp(p);
  161.     return(p);
  162. }
  163.  
  164. /*
  165.  - outopen - acquire an output file
  166.  */
  167. FILE *
  168. outopen(name)
  169. char *name;
  170. {
  171.     FILE *f;
  172.  
  173.     f = fopen(name, "w");
  174.     if (f == NULL)
  175.         error("unable to create temporary `%s'", name);
  176.     if (debug)
  177.         fprintf(stderr, "output into %s\n", name);
  178.  
  179.     return(f);
  180. }
  181.  
  182. /*
  183.  - outclose - close output file, moving it to the right place
  184.  *
  185.  * Names are based on the current time in hopes of keeping input in order.
  186.  */
  187. void
  188. outclose(f, tmpname)
  189. FILE *f;
  190. char *tmpname;
  191. {
  192.     register char *p;
  193.     register char *name;
  194.     register int ntries;
  195.     time_t now;
  196.     extern int errno;
  197.  
  198.     if (fclose(f) == EOF)
  199.         error("fclose error on file `%s'", tmpname);
  200.  
  201.     p = fullartfile("in.coming/");
  202.     name = emalloc(strlen(p) + 20);    /* plenty for a number */
  203.     (void) strcpy(name, p);
  204.     p = name + strlen(name);
  205.  
  206.     ntries = 0;
  207.     for (;;) {
  208.         now = time((time_t *)NULL);
  209.         sprintf(p, "%ld", now);
  210.         if (debug)
  211.             fprintf(stderr, "trying renaming to %s\n", name);
  212.         if (link(tmpname, name) >= 0)
  213.             break;        /* NOTE BREAK OUT */
  214.         if (errno != EEXIST)    /* something strange is wrong */
  215.             error("unable to link `%s'", tmpname);
  216.         errno = 0;
  217.         if (ntries > MAXTRIES)    /* sanity check */
  218.             error("too many attempts to link `%s'", tmpname);
  219.         if (debug)
  220.             fprintf(stderr, "failed\n");
  221.         sleep(2);    /* avoid rumored race in 1-sec sleep */
  222.         ntries++;
  223.     }
  224.  
  225.     if (debug)
  226.         fprintf(stderr, "succeeded\n");
  227.     (void) unlink(tmpname);
  228. }
  229.  
  230. /*
  231.  - cunskip - inspect block for silly #! cunbatch headers
  232.  */
  233. int                /* number of chars at start to skip */
  234. cunskip(bufp, count)
  235. char *bufp;
  236. int count;
  237. {
  238.     static char goop[] = "cunbatch";
  239. #    define    GOOPLEN    (sizeof(goop)-1)    /* strlen(goop) */
  240.     static char goop2[] = "c7unbatch";
  241. #    define    GOOP2LEN    (sizeof(goop2)-1)    /* strlen(goop2) */
  242.     register char *p;
  243.     register int nleft;
  244.  
  245.     nleft = count;
  246.     p = bufp;
  247.  
  248.     if (nleft < 2)                /* no room for a header */
  249.         return(0);
  250.     if (*p++ != '#' || *p++ != '!')        /* doesn't start with #! */
  251.         return(0);
  252.     nleft -= 2;
  253.  
  254.     /* skip space */
  255.     while (nleft > 0 && (*p == ' ' || *p == '\t')) {
  256.         p++;
  257.         nleft--;
  258.     }
  259.  
  260.     /* recognize headers (the +1s ensure room for the newline) */
  261.     if (nleft >= GOOPLEN+1 && STREQN(p, goop, GOOPLEN)) {
  262.         p += GOOPLEN;
  263.         nleft -= GOOPLEN;
  264.     } else if (nleft >= GOOP2LEN+1 && STREQN(p, goop2, GOOP2LEN)) {
  265.         p += GOOP2LEN;
  266.         nleft -= GOOP2LEN;
  267.     } else                    /* no header */
  268.         return(0);
  269.  
  270.     /* skip more space */
  271.     while (nleft > 0 && (*p == ' ' || *p == '\t')) {
  272.         p++;
  273.         nleft--;
  274.     }
  275.  
  276.     if (nleft == 0 || *p++ != '\n')        /* didn't end properly */
  277.         return(0);
  278.  
  279.     return(p - bufp);
  280. }
  281.  
  282. /*
  283.  - unprivileged - drop setuidness if configuration is overridden
  284.  */
  285. void
  286. unprivileged()
  287. {
  288.     setgid(getgid());
  289.     setuid(getuid());
  290. }
  291.